package net.gdface.bean;

import java.util.Map;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import net.gdface.bean.BaseBeanPropertySupport.DiffNode;
import static com.google.common.base.Preconditions.checkNotNull;
/**
 * @author guyadong
 * @since 2.7.0
 */
public abstract class BeanDifference {
	private BaseBeanPropertySupport instance;
	/**
	 * return left value from right
	 * @param right
	 */
	protected abstract Object left(Object right);
	
    protected BeanDifference(BaseBeanPropertySupport instance) {
		super();
		this.instance = checkNotNull(instance,"instance is null");
	}

	/**
     * 返回两个对象之间差异的字段
     * @param right
     */
	public Map<String,DiffNode> different(Object right){
		return different(right,null,null, true, new String[0]);
	}
    /**
	 * 返回两个对象之间差异的字段
	 * @param right
	 * @param focusName
	 */
	public Map<String,DiffNode> different(Object right,
			String focusName){
		return different(right,Predicates.<String>alwaysTrue(),null, true, focusName);
	}

	/**
     * 返回两个对象之间差异的字段
     * @param right
     * @param focusNames
     */
	public Map<String,DiffNode> different(Object right,
			String... focusNames){
		return different(right,Predicates.<String>alwaysTrue(),null, true, focusNames);
	}
	/**
	 * 返回两个对象之间差异的字段
	 * @param right
	 * @param focusNames
	 */
	public Map<String,DiffNode> different(Object right,
			Iterable<String>focusNames){
		return different(right,Predicates.<String>alwaysTrue(),null, focusNames, true);
	}
	/**
	 * 返回两个对象之间差异的字段
	 * @param right
	 * @param originNameFilter
	 * @param focusNames
	 */
	public Map<String,DiffNode> different(Object right,Predicate<String> originNameFilter,
			Iterable<String>focusNames){
		return different(right,originNameFilter,null, focusNames, true);
	}
	/**
	 * 返回两个对象之间差异的字段
	 * @param right
	 * @param originNameFilter
	 * @param focusNames
	 */
	public Map<String,DiffNode> different(Object right,Predicate<String> originNameFilter,
			String...focusNames){
		return different(right,originNameFilter,null, true,focusNames);
	}
	/**
	 * 返回两个对象之间差异的字段，返回不同的字段差异信息
	 * @see #different(Object, Predicate, String[], boolean, String...)
	 * @param right
	 * @param originNameFilter
	 * @param forceExcludeNames 强制排除比较的字段名
	 * @param includeRequired 为{@code true}时{@code focusNames}为白名单,否则为黑名单
	 * @param focusNames 比较字段黑/白名单
	 */
	public Map<String,DiffNode> different(Object right,
			Predicate<String> originNameFilter,
			String[] forceExcludeNames, 
			boolean includeRequired, 
			String... focusNames){
		return instance.different(left(right), right, originNameFilter, forceExcludeNames, includeRequired, focusNames);
	}
	/**
	 * 返回两个对象之间差异的字段，返回不同的字段差异信息
	 * @param right
	 * @param originNameFilter
	 * @param forceExcludeNames 强制排除比较的字段名
	 * @param focusNames 比较字段黑/白名单
	 * @param includeRequired 为{@code true}时{@code focusNames}为白名单,否则为黑名单
	 */
	public Map<String,DiffNode> different(Object right,
			Predicate<String> originNameFilter,
			Iterable<String> forceExcludeNames, 
			Iterable<String> focusNames, 
			boolean includeRequired){
		return instance.different(left(right), right, originNameFilter, forceExcludeNames, focusNames, includeRequired);
	}
}
